#include "thread.h"

#include <sys/syscall.h>    // 系统调用头文件
// 在cpp文件中使用<iostream>
#include <iostream>
#include <unistd.h>         // POSIX标准头文件

namespace zsylar
{
// 线程局部存储变量，用于保存当前线程信息
// t_thread:只想当前线程的指针
// t_thread_name:当前线程的名称
static thread_local Thread* t_thread          = nullptr;
static thread_local std::string t_thread_name = "UNKNOWN";

// 获取当前线程ID
pid_t Thread::GetThreadId()
{
    return syscall(SYS_gettid);
}

// 获取当前线程指针对象
Thread* Thread::GetThis()
{
    return t_thread;
}

// 获取当前线程名称
// 添加static，表示该函数的作用域仅限于当前源文件（编译单元），其他文件无法访问。
// 类内使用static：不依赖对象实例​；无this指针；可操作静态成员​
const std::string& Thread::GetName()
{
    return t_thread_name;
}

// 设置当前线程名称
void Thread::SetName(const std::string& name)
{
    if (t_thread) 
    {
        t_thread->m_name = name;
    }
    t_thread_name = name;
}

// 构造函数
Thread::Thread(std::function<void()> cb, const std::string& name):
    m_cb(cb), m_name(name)
{
    // 创建POSIX线程
    int rt = pthread_create(&m_thread, nullptr, &Thread::run, this);
    if (rt)
    {
        std::cerr << "pthread_create thread fail, rt = " << rt << " name = " << name;
        throw std::logic_error("pthread_create error");
    }
    // 使用信号量等待线程函数完成初始化
    m_semaphore.wait();
}

Thread::~Thread()
{
    if (m_thread)
    {
        pthread_detach(m_thread);
        m_thread = 0;
    }
}

// 等待线程结束
void Thread::join()
{
    if (m_thread)
    {
        int rt = pthread_join(m_thread, nullptr);
        if (rt)
        {
            std::cerr << "pthread_join failed, rt = " << rt << ", name = " << m_name << std::endl;
            throw std::logic_error("pthread_join error");
        }
        m_thread = 0;
    }
}

// ？？== ？？ TODO: 学习pthread相关知识 //

// 线程入口函数,传入线程对象指针
void* Thread::run(void* arg)
{
    Thread* thread = (Thread*)arg;
    
    // 设置线程局部存储
    t_thread        = thread;
    t_thread_name   = thread->m_name;
    thread->m_id    = GetThreadId();

    // 设置线程名称
    pthread_setname_np(pthread_self(), thread->m_name.substr(0, 15).c_str());

    // 获取并交换回调函数
    std::function<void()> cb;
    cb.swap(thread->m_cb);  // 使用swap减少智能指针的引用计数

    // 通知构造函数线程初始化完成
    thread->m_semaphore.signal();

    // 执行回调函数
    cb();
    return 0;
}

}